#include "CocosPCH.h" 

#include "CoCImageNode.h"

// implementation of CoCImageNode

CoCImageNode::CoCImageNode()
: m_uVao(0)
, m_uVbo(0)
, m_nBufferCount(0)
, m_pBuffer(NULL)
{
    m_sBlendFunc.src = CC_BLEND_SRC;
    m_sBlendFunc.dst = CC_BLEND_DST;
}

CoCImageNode::~CoCImageNode()
{
    m_pBuffer = NULL;    
}

CoCImageNode* CoCImageNode::create(int count, V3F_C4B_T2F* vertex, Texture2D *pTexture)
{
    CoCImageNode* pRet = new CoCImageNode();
    if (pRet && pRet->initWithData(count, vertex, pTexture))
    {
        pRet->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(pRet);
    }
    
    return pRet;
}

bool CoCImageNode::initWithData(int count, V3F_C4B_T2F *vertex, Texture2D *pTexture)
{    
    setGLProgram(ShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR));
	m_nBufferCount = count;
	m_pBuffer = vertex;
	m_pobTexture = pTexture;
	m_colors = Color4B(255, 255, 255, 255);

	float fMinX, fMinY, fMaxX, fMaxY;
	fMinX = m_pBuffer[0].vertices.x;
	fMaxX = m_pBuffer[0].vertices.x;
	fMinY = m_pBuffer[0].vertices.y;
	fMaxY = m_pBuffer[0].vertices.y;
	for(int i = 1; i < m_nBufferCount; i++)
	{
		fMinX = m_pBuffer[i].vertices.x < fMinX ? m_pBuffer[i].vertices.x : fMinX;
		fMaxX = m_pBuffer[i].vertices.x > fMaxX ? m_pBuffer[i].vertices.x : fMaxX;
		fMinY = m_pBuffer[i].vertices.y < fMinY ? m_pBuffer[i].vertices.y : fMinY;
		fMaxY = m_pBuffer[i].vertices.y > fMaxY ? m_pBuffer[i].vertices.y : fMaxY;
	}
	m_Rect.origin.x = fMinX;
	m_Rect.origin.y = fMinY;
	m_Rect.size.width = fMaxX-fMinX;
	m_Rect.size.height = fMaxY-fMinY;

	updateBlendFunc();

    return true;
}

void CoCImageNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
	if(!isVisible())
		return ;
	
    _customCommand.init(_globalZOrder, transform, flags);
    _customCommand.func = CC_CALLBACK_0(CoCImageNode::onDraw, this, transform, flags);
    renderer->addCommand(&_customCommand);
}
void CoCImageNode::onDraw(const Mat4 &transform, uint32_t flags)
{
    GL::blendFunc(m_sBlendFunc.src, m_sBlendFunc.dst);
    GL::bindTexture2D(m_pobTexture->getName());
    GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);

    _glProgramState->applyGLProgram(transform);
    _glProgramState->applyUniforms();
    GLProgram *pProg = _glProgramState->getGLProgram();
    GLint nLocal = pProg->getUniformLocationForName(GLProgram::UNIFORM_NAME_MASKENABLED);
    _glProgramState->getGLProgram()->setUniformLocationWith1i(nLocal, 0);
    for (int i = 0; i < m_nBufferCount; i++)
    {
        m_pBuffer[i].colors = m_colors;
    }

    long offset = (long)m_pBuffer;

    // vertex
    int diff = offsetof(V3F_C4B_T2F, vertices);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (void*)(offset + diff));
    // texCoods
    diff = offsetof(V3F_C4B_T2F, texCoords);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (void*)(offset + diff));
    // color
    diff = offsetof(V3F_C4B_T2F, colors);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), (void*)(offset + diff));
    glDrawArrays(GL_TRIANGLE_FAN, 0, m_nBufferCount);
}

BlendFunc CoCImageNode::getBlendFunc()
{
    return m_sBlendFunc;
}

void CoCImageNode::setBlendFunc(BlendFunc blendFunc)
{
    m_sBlendFunc = blendFunc;
}

void CoCImageNode::setColor(Color4B color)
{
	m_colors = color;
}

Rect CoCImageNode::getRect()
{
	return m_Rect;
}

void CoCImageNode::setTexture(Texture2D *texture)
{
	m_pobTexture = texture;
	updateBlendFunc();
}

Texture2D* CoCImageNode::getTexture(void)
{
    return m_pobTexture;
}

void CoCImageNode::updateBlendFunc(void)
{
    // it is possible to have an untextured sprite
    //if (! m_pobTexture || ! m_pobTexture->hasPremultipliedAlpha())
    {
        m_sBlendFunc.src = GL_SRC_ALPHA;
        m_sBlendFunc.dst = GL_ONE_MINUS_SRC_ALPHA;
    }
    //else
    //{
        //m_sBlendFunc.src = CC_BLEND_SRC;
        //m_sBlendFunc.dst = CC_BLEND_DST;
    //    setOpacityModifyRGB(true);
    //}
}